package com.itheima.security;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.service.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import pojo.Permission;
import pojo.Role;
import pojo.User;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
 * 认证过程中的处理类
 *
 * 要从数据库动态查询用户信息，就必须按照spring security框架的要求提供一个实现UserDetailsService接口的实现类，
 * 并按照框架的要求进行配置即可。框架会自动调用实现类中的方法并自动进行密码校验
 */
/**
 * 认证和授权
 * 被拦截到的资源，会自动进入这里
 */
@Component
public class SpringSecurityUserService implements UserDetailsService {
    
    @Reference
    private UserService userService;
    
    /**
     * 根据用户名查询用户
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.findUserByUsername(username);
        //判断用户是否存在
        if(user == null){
            return null;//用户名为空
        }
    
        //存储登录成功的用户被赋予的一些权限
        List<GrantedAuthority> list = new ArrayList<>();
        
        Set<Role> roles = user.getRoles();
        for (Role role : roles) {
            String keyword = role.getKeyword();//根据角色获取角色关键字
            list.add(new SimpleGrantedAuthority(keyword));//给用户赋予角色
            
            Set<Permission> permissions = role.getPermissions();//根据角色获取权限
            for (Permission permission : permissions) {
                String keyword1 = permission.getKeyword();
                list.add(new SimpleGrantedAuthority(keyword1));//给用户赋予权限
            }
        }
        String pwd_db = user.getPassword();//加密了的密码,所有不用明文加{noop},(在spring-security.xml中设置了密码加密策略)
    
        org.springframework.security.core.userdetails.User user1 = new org.springframework.security.core.userdetails.User(username, pwd_db, list);
       
        //将用户名和数据库中用户密码一同交给框架去认证和授权，认证通过便赋予权限
        return user1;
    }
}
